package com.jzo2o.customer.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jzo2o.common.expcetions.ForbiddenOperationException;
import com.jzo2o.common.model.PageResult;
import com.jzo2o.customer.enums.AuditStatusEnum;
import com.jzo2o.customer.enums.CertificationStatusEnum;
import com.jzo2o.customer.mapper.AgencyCertificationAuditMapper;
import com.jzo2o.customer.mapper.AgencyCertificationMapper;
import com.jzo2o.customer.model.domain.AgencyCertification;
import com.jzo2o.customer.model.domain.AgencyCertificationAudit;
import com.jzo2o.customer.model.domain.ServeProvider;
import com.jzo2o.customer.model.dto.request.AgencyCertificationAuditAddReqDTO;
import com.jzo2o.customer.model.dto.request.AgencyCertificationAuditPageQueryReqDTO;
import com.jzo2o.customer.model.dto.request.CertificationAuditReqDTO;
import com.jzo2o.customer.model.dto.response.AgencyCertificationAuditResDTO;
import com.jzo2o.customer.model.dto.response.RejectReasonResDTO;
import com.jzo2o.customer.service.IAgencyCertificationService;
import com.jzo2o.customer.service.IServeProviderService;
import com.jzo2o.mvc.utils.UserContext;
import com.jzo2o.mysql.utils.PageHelperUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;

/**
 * @author xd
 */
@Service
public class AgencyCertificationServiceImpl extends ServiceImpl<AgencyCertificationMapper, AgencyCertification> implements IAgencyCertificationService {
    @Resource
    private AgencyCertificationAuditMapper agencyCertificationAuditMapper;

    @Resource
    private IServeProviderService serveProviderService;
    /**
     * @param dto {@code AgencyCertificationAuditAddReqDTO} 申请材料封装类
     * @author xd
     * 机构认证申请
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void agencyCertification(AgencyCertificationAuditAddReqDTO dto) {
        //1.判断统一社会信用代码是否重复,判断机构的营业执照是否重复
        Integer count = lambdaQuery().eq(AgencyCertification::getIdNumber, dto.getIdNumber()).or().eq(AgencyCertification::getBusinessLicense, dto.getBusinessLicense()).count();
        if (count > 0) {
            throw new ForbiddenOperationException("社会信用代码或营业执照出现重复");
        }
        //2.将数据保存到审核表中
        AgencyCertificationAudit certificationAudit = BeanUtil.toBeanIgnoreError(dto, AgencyCertificationAudit.class);
        //设置机构id
        certificationAudit.setServeProviderId(UserContext.currentUser().getId());
        //设置审核状态和认证状态
        certificationAudit.setCertificationStatus(CertificationStatusEnum.PROGRESSING.getStatus());
        certificationAudit.setAuditStatus(AuditStatusEnum.NOT_REVIEWED.getStatus());
        agencyCertificationAuditMapper.insert(certificationAudit);
        //将认证申请表的认证状态改成认证中
        AgencyCertification certification = lambdaQuery().eq(AgencyCertification::getId, UserContext.currentUser().getId()).one();
        if (ObjectUtil.isNull(certification)) {
            AgencyCertification agencyCertification = BeanUtil.toBeanIgnoreError(dto, AgencyCertification.class);
            agencyCertification.setCertificationStatus(CertificationStatusEnum.PROGRESSING.getStatus());
            agencyCertification.setId(UserContext.currentUser().getId());
            save(agencyCertification);
        }else {
            lambdaUpdate().set(AgencyCertification::getCertificationStatus,CertificationStatusEnum.PROGRESSING.getStatus()).eq(AgencyCertification::getId,UserContext.currentUser().getId()).update();
        }
        //同步服务者名称
        serveProviderService.lambdaUpdate().set(ServeProvider::getName,certificationAudit.getName()).eq(ServeProvider::getId,certificationAudit.getServeProviderId()).update();
    }

    /**
     * @return {@code String} 拒绝原因
     * @author xd
     * 查看机构申请认证失败原因
     */
    @Override
    public RejectReasonResDTO getRejectReason() {
        Long id = UserContext.currentUserId();
        String reason = agencyCertificationAuditMapper.selectReasonByServeProviderId(id);
        return new RejectReasonResDTO(reason);
    }

    /**
     * @param dto 分页条件实体类
     * @return 分页结果包装类
     * @author xd
     * 审核机构认证分页查询
     */
    @Override
    public PageResult<AgencyCertificationAuditResDTO> pageQuery(AgencyCertificationAuditPageQueryReqDTO dto) {
        return PageHelperUtils.selectPage(dto, () -> agencyCertificationAuditMapper.pageQuery(dto));
    }

    /**
     * @param dto {@code CertificationAuditReqDTO} 包装认证状态和驳回原因
     * @param id  {@code Long} 认证申请信息id
     * @author xd
     * 审核机构认证信息
     */
    @Override
    @Transactional
    public void audit(CertificationAuditReqDTO dto, Long id) {
        AgencyCertificationAudit agencyCertificationAudit = agencyCertificationAuditMapper.selectById(id);
        //判断传来的申请信息id是否为假
        if (ObjectUtil.isNull(agencyCertificationAudit)) {
            throw new ForbiddenOperationException("缺少该认证申请信息");
        }
        //如果该审核信息的审核状态为已审核也禁止审核
        if (agencyCertificationAudit.getAuditStatus() == AuditStatusEnum.REVIEWED.getStatus()) {
            throw new ForbiddenOperationException("该申请已审核,请勿重复操作");
        }
        AgencyCertificationAudit certificationAudit = BeanUtil.toBeanIgnoreError(dto, AgencyCertificationAudit.class);
        certificationAudit.setAuditStatus(AuditStatusEnum.REVIEWED.getStatus());
        certificationAudit.setAuditorId(UserContext.currentUserId());
        certificationAudit.setAuditorName(UserContext.currentUser().getName());
        certificationAudit.setAuditTime(LocalDateTime.now());
        certificationAudit.setUpdateTime(LocalDateTime.now());
        certificationAudit.setId(id);
        //修改审核结果
        agencyCertificationAuditMapper.audit(certificationAudit);
        //同步更新认证申请表
        AgencyCertificationAudit audit = agencyCertificationAuditMapper.selectById(id);
        //审核结束,需要同步到认证申请信息表中
        AgencyCertification agencyCertification = BeanUtil.toBeanIgnoreError(audit, AgencyCertification.class);
        //设置id为机构id
        agencyCertification.setId(audit.getServeProviderId());
        agencyCertification.setCertificationTime(audit.getAuditTime());
        updateById(agencyCertification);
    }
}
